# vxagent

Произведен анализ упаковки программного обеспечения "vxagent" в RPM.

## Объект тестирования

* имя файла: `vxagent-2.0.0.2306_amd64.rpm`
* хеш MD5: `3497695532a2358744498a9f0f5a8cfb`

## Анализ пакета

### Скриптлеты пакеты

В пакете следующие скриптлеты:

```
$ rpm -q vxagent-2.0.0.2306_amd64.rpm  --scripts
postinstall scriptlet (using /bin/bash):
ln -s /usr/lib64/librt.so.1 /usr/lib64/librt.so 2>/dev/null || true
ln -s /usr/lib64/libpthread.so.0 /usr/lib64/libpthread.so 2>/dev/null || true
chmod +x /opt/pt/vxagent/bin/vxagent && chown root:root /opt/pt/vxagent/bin/vxagent

/opt/pt/vxagent/bin/vxagent -connect $VXSERVER_CONNECT -command install
/opt/pt/vxagent/bin/vxagent -command start
preuninstall scriptlet (using /bin/bash):
/opt/pt/vxagent/bin/vxagent -command stop || true
if pgrep -f vxagent &>/dev/null; then
  kill -9  &>/dev/null || true
fi
/opt/pt/vxagent/bin/vxagent -command uninstall || true
postuninstall scriptlet (using /bin/bash):
if ! [ -d /opt/ ]; then
  mkdir /opt || true
fi
rm -rf /opt/pt/vxagent || true
rmdir /opt/pt/ || true
```

postinstall выполняется после установки пакета, а postuninstall после удаления пакета. При обновлении пакета в одной транзакции ставится новый пакет и удаляется старый. Сначала будет выполнен `%post` нового пакета, а затем будет выполнен `%postun` старого пакета (/opt/pt/vxagent будет удалён). Первым аргументом скриптлету приходит количество пакетов, остающихся после транзакции, что позволяет определить, обновление это или полное удаление. Подробно описано здесь: [https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/](https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/). Обратите внимание на раздел "Ordering".

Однако при установке такого пакета поверх старой версии все равно сработает `%postun` старой версии и удалит созданное в процессе установки предыдущей версии пакета.

Не очень понятна необходимость всех указанных скриптов. Всё что есть в этих скриптах необходимо делать с помощью пакетного менеджера.

#### Симлинки на библиотеки

В списке [упакованных файлов](#упакованные-файлы) нет файлов `/usr/lib64/librt.so.1` и `/usr/lib64/libpthread.so.0`, но даже если бы и были, то симлинки нужно так же прописывать в разделе `%install` спека и в разделе `%files`, чтобы пакетный менеджер о них знал. Недопустимо создавать в системе файлы не принадлежащие никакому пакету и о которых пакетный менеджер ничего не знает.

Выше описание как необходимо делать в общем случае для разных файлов. Конкретно тут симлинки `/usr/lib64/librt.so.1` и `/usr/lib64/libpthread.so.0` вообще недопустимо делать таким образом. Это недопустимое вмешательство в систему. Можно запаковать их в своём каталоге в `/opt...` и сделать `RPATH`.

#### Изменение режима доступа к файлу в обход пакетного менеджера

`chmod +x /opt/pt/vxagent/bin/vxagent && chown root:root /opt/pt/vxagent/bin/vxagent`

Эти операции необходимо выполнять в секции `%install` спека. При необходимости, можно задать `%attr` в секции `%files`

В rpm существует функционал проверки целостности пакета (`rpm -V`), он будет выдавать, что права на файл не целостны, если менять их скриптом.

#### Запуск сервиса

```... -command install``` по всей видимости запускает какую-то установку с вмешательством в файлы системы, не принадлежащие пакету. Это недопустимо. Все файлы и все изменения должны быть известны пакетному менеджеру. В противном случае это как раз и является тем опасным сценарием, который, по идее, и должен отлавливать этот агент, а он, получается, сам себя так ведёт.

Запуск сервисов необходимо настроить с помощью стандартных для системы инструментов. Например, сделать сервис systemd. Создать файл для сервиса `vxagent.service` и положить его в секции `%install` в `%_unitdir` и в этой же секции прописать автозапуск:

```
cat > %{buildroot}%{_presetdir}/80-vxagent.preset << 'EOF'
enable vxagent.service
EOF
```

После чего можно (но не обязательно) прописать включение и отключение в `%post` и `%preun`, например так:

```
%post
%systemd_post vxagent.service

%preun
%systemd_preun vxagent.service

```

Ну или другим способом, но это, по сути, всё что может быть нужно именно в скриптах.

### Содержимое пакета

### Упакованные файлы

<a id="упакованные-файлы"></a>

```
$ rpm -q vxagent-2.0.0.2306_amd64.rpm  -l
/opt/pt/vxagent/bin
/opt/pt/vxagent/bin/vxagent
/opt/pt/vxagent/data
/opt/pt/vxagent/logs
/usr/lib/.build-id
/usr/lib/.build-id/9c
/usr/lib/.build-id/9c/a8b17463efcf328dfe35911ddcb8b9c0d02eaa
```


#### Не все файлы принадлежат пакету

Как уже написано выше, скрипт пытается работать с файлами библиотек, которых в пакете просто не упаковано.

#### Лишняя debug-информация

В пакете присутствует каталог `/usr/lib/.build-id` и файлы в нем, это не имеет смысла. Рекомендуем выставить макрос `%_build_id_links` в значение `alldebug` (https://github.com/rpm-software-management/rpm/blob/56558a5a6/macros.in#L498).

### Зависимости пакета

У пакета следующие зависимости:

```
$ rpm -qR vxagent-2.0.0.2306_amd64.rpm 
/bin/bash
/bin/bash
/bin/bash
bash
glibc
initscripts
ld-linux-x86-64.so.2()(64bit)
ld-linux-x86-64.so.2(GLIBC_2.3)(64bit)
libc.so.6()(64bit)
libc.so.6(GLIBC_2.14)(64bit)
libc.so.6(GLIBC_2.17)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
libc.so.6(GLIBC_2.7)(64bit)
libdl.so.2()(64bit)
libdl.so.2(GLIBC_2.2.5)(64bit)
libgcc
libgcc_s.so.1()(64bit)
libgcc_s.so.1(GCC_3.0)(64bit)
libgcc_s.so.1(GCC_3.3)(64bit)
libm.so.6()(64bit)
libm.so.6(GLIBC_2.2.5)(64bit)
libpthread.so.0()(64bit)
libpthread.so.0(GLIBC_2.12)(64bit)
libpthread.so.0(GLIBC_2.2.5)(64bit)
libpthread.so.0(GLIBC_2.3.2)(64bit)
libpthread.so.0(GLIBC_2.3.3)(64bit)
libstdc++
libstdc++.so.6()(64bit)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rtld(GNU_HASH)
systemd
```

Чтобы пакет был дистрибутивоуниверсальным, рекомендуем заменить зависимости на следующий вид: `libfoo.so.N()(64bit)`. RPM может проставить такие зависимости автоматически, если не отключать AutoReq.  Рекомендуем ознакомиться с материалом: https://nixtux.ru/1268

В связи с вышеизложенным, например, автоматом нашлось `libgcc_s.so.1()(64bit)`, поэтому указание вручную `libgcc` излишне, ну или стоило прямо так и указывать `Requires: libgcc_s.so.1%{_arch_tag_suffix}` и т.п.

## Информация о пакете

```
$ rpm -qi vxagent-2.0.0.2306_amd64.rpm
Name        : vxagent
Version     : 2.0.0.2306
Release     : 2306
Architecture: amd64
Install Date: (not installed)
Group       : Unspecified
Size        : 32883182
License     : -
Signature   : (none)
Source RPM  : vxagent-2.0.0.2306-2306.src.rpm
Build Date  : Чт 12 окт 2023 17:56:00
Build Host  : runner-8raqfx6c-project-8497-concurrent-0
Summary     : MaxPatrol EDR agent service
Description :
VX agent
```


Не указана лицензия, описание и группа. Чтобы в пакетном менеджере пакет был отображён не отдельно непонятно где, следует указать группу к которой относится утилита. Стандартные группы собраны, например, тут: http://wiki.rosalab.ru/en/index.php/Packaging_group

Summary и Description было бы здорово дублировать на русском языке.

```
...

Summary(ru_RU.UTF-8): 
...
%description -l ru_RU.UTF-8
...
```

Пример:

https://hub.mos.ru/mos/pkgs/mos-docdir/-/blob/main/mos-docdir.spec
